package com.golxen.framework.netty.session.game;


import com.golxen.framework.PBPacket.PBPacket;
import com.golxen.framework.netty.NettyServices;
import com.golxen.framework.netty.session.base.NettyChannelSession;
import com.golxen.framework.netty.session.base.ServerLinkedGroup;
import com.golxen.utils.LogUtil;
import com.google.protobuf.Message;
import io.netty.channel.ChannelHandlerContext;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

public class GameServerLinkedSet {

	private static int agentCount = 0;
	private static Map<Integer, ServerLinkedGroup> agentLinkedSet = new ConcurrentHashMap<>();
	private static Object lockObj = new Object();

	public static void init(int count) {
		agentCount = count;
	}

	public static void removeLinkedClient(ChannelHandlerContext ctx) {
		ServerLinkedGroup client = getLinkedClient(ctx);
		if (client == null) {
			return;
		}

		agentLinkedSet.remove(client.getServerIndex());
	}

	public static ServerLinkedGroup getLinkedClient(ChannelHandlerContext ctx) {
		return ctx.channel().attr(NettyServices.LINKED_CLIENT).get();
	}

	public static void send(long userId, PBPacket packet) {
		Message msg = packet.getMessage();

		if (userId <= 0) {
			sendSingle(packet);
		} else {
			if (agentCount == 0) {
				LogUtil.COMMON.error("not agent");
				return;
			}
			long idx = userId % agentCount;
			ServerLinkedGroup group = agentLinkedSet.get(idx);
			if (group != null) {
				group.sendPacket(userId, packet);
			} else {
				LogUtil.COMMON.error("can not found agent connection , userId = " + userId + " code : " + packet.getCode()
						+ " . packet forward failed." + " .idx : " + idx + "  .agentLinkedSet size:"
						+ agentLinkedSet.size());
			}
		}
	}

	private static void sendSingle(PBPacket packet) {
		for (ServerLinkedGroup group : agentLinkedSet.values()) {
			group.write(packet.getPlayerId(), packet);
			break;
		}
	}

	public static ServerLinkedGroup addAgentLinkedGroup(int serverIndex, NettyChannelSession session, int count,
														int linkIndex) {
		synchronized (lockObj) {
			if (agentLinkedSet.containsKey(serverIndex)) {
				agentLinkedSet.get(serverIndex).addSession(session, linkIndex);
			} else {
				ServerLinkedGroup group = new ServerLinkedGroup(count, serverIndex);
				group.addSession(session, linkIndex);
				agentLinkedSet.put(serverIndex, group);
			}
			return agentLinkedSet.get(serverIndex);
		}
	}
}
